package org.archimetrix.architectureprognosis.ui.util;


import java.util.HashMap;
import java.util.Map;

import org.archimetrix.commons.wizards.WizardConstants;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;

import eu.qimpress.samm.staticstructure.ComponentType;
import eu.qimpress.samm.staticstructure.PrimitiveComponent;
import eu.qimpress.samm.staticstructure.Repository;
import eu.qimpress.sourcecodedecorator.ComponentImplementingClassesLink;
import eu.qimpress.sourcecodedecorator.SourceCodeDecoratorRepository;


/**
 * This class contains helper methods for components.
 * 
 * @author mcp
 * @author Last editor: $Author$
 * @version $Revision$ $Date$
 * 
 */
public final class ComponentsUtil
{
   private static final String RESOURCE_SEGMENT = "resource";

   private static ComponentsUtil instance = null;

   private SourceCodeDecoratorRepository scd;

   private Repository samm;

   private Map<ComponentType, ComponentImplementingClassesLink> componentClasses;


   private ComponentsUtil()
   {
   }


   public static ComponentsUtil get()
   {
      if (instance == null)
      {
         instance = new ComponentsUtil();
      }
      return instance;
   }


   /**
    * Returns the componentImplementingClassesLink that belongs to the given component.
    * 
    * @param component a primitive component from a SAMM
    * @return a component implementing classes link of the according SCDM
    */
   public ComponentImplementingClassesLink getComponentImplementingClassesLinkForComponent(final PrimitiveComponent component)
   {
      if (this.componentClasses == null)
      {
         this.componentClasses = new HashMap<ComponentType, ComponentImplementingClassesLink>();
      }
      ComponentImplementingClassesLink componentImplementingClassesLink = this.componentClasses.get(component);
      if (componentImplementingClassesLink != null)
      {
         return componentImplementingClassesLink;
      }
      else
      {
         SourceCodeDecoratorRepository scd = getSourceCodeDecoratorModel((Repository) component.eContainer());
         for (ComponentImplementingClassesLink link : scd.getComponentImplementingClassesLink())
         {
            EcoreUtil.resolveAll(link.getComponent());
            if (link.getComponent().getId().equals(component.getId()))
            {
               this.componentClasses.put(component, link);
               return link;
            }
         }
      }
      return null;
   }


   /**
    * Creates a short name from the component name generated by SoMoX.
    * 
    * @param component
    * @return
    */
   public String createShortComponentName(final ComponentType component)
   {
      String[] componentNameArray = component.getName().split(" ");
      String componentName = componentNameArray[1] + " " + componentNameArray[3];
      return componentName;
   }


   private SourceCodeDecoratorRepository getSourceCodeDecoratorModel(final Repository sammRepository)
   {
      if (this.scd == null || sammRepository != this.samm)
      {
         this.samm = sammRepository;
         StringBuilder path = createSCDMPath(sammRepository);
         URI scdmFileUri = URI.createPlatformResourceURI(path.toString(), true);
         ResourceSet scdmRess = new ResourceSetImpl();
         Resource scdmRes = scdmRess.getResource(scdmFileUri, true);
         this.scd = (SourceCodeDecoratorRepository) scdmRes.getContents().get(0);
      }
      return this.scd;
   }


   private StringBuilder createSCDMPath(final Repository sammRepository)
   {
      String resourceUriPath = sammRepository.eResource().getURI().path();
      String modelsPath = resourceUriPath.split(RESOURCE_SEGMENT)[1].split("\\.")[0];
      StringBuilder path = new StringBuilder(modelsPath);
      path.append(".");
      path.append(WizardConstants.SOURCECODEDECORATOR_FILE_EXTENSION);
      return path;
   }
}
